package org.peacewing.swingui;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.List;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.text.BadLocationException;

import org.light.exception.ValidateException;

import jsyntaxpane.DefaultSyntaxKit;
import jsyntaxpane.SyntaxDocument;
import jsyntaxpane.Token;
import jsyntaxpane.actions.CaretMonitor;

public class AppGui extends JFrame implements MouseListener, ActionListener {
	private static final long serialVersionUID = -6937905461006207016L;

	private JMenuBar mb;
	
	private JMenu mFile;
	
	private JMenu mSample;

	private JMenu mHelp;	

	private JMenuItem miAbout;

	private JMenuItem miNew;
	
	private JMenuItem miOpen;

	private JMenuItem miSave;

	private JMenuItem miSaveAs;

	private JMenuItem miClose;	
	
	private JMenuItem miExit;
	
	private JMenuItem miReadme;
	
	private JMenuItem miInstall;
	
	private JMenuItem miUserManual;
	
	private JMenuItem miTheory1;
	
	private JMenuItem miTheory2;
	
	private JMenuItem miTheory3;
	
	private JMenuItem miTheory4;
	
	private JMenuItem miGift;
	
	private JMenuItem miGenerateSample;

	private JMenuItem miMagic;

	private JMenuItem miAdvanced;

	private JMenuItem miOne;

	private JMenuItem miEmployeeTest;

	private JMenuItem miUserSystem;

	private JMenuItem miFields;

	private JMenuItem miSports;

	private JMenuItem miProject;
	
	private JMenuItem mCompile;
	
	private JMenuItem miCompile;
	
	private JMenuItem miIgnore;
	
	private FileActions fileActions;
	
	public static void main(String [] args) {
		try{	
			java.awt.EventQueue.invokeLater(new Runnable() {

	            @Override
	            public void run() {
	            	try {
	            		new AppGui().setVisible(true);
	            	} catch (Exception e){
	            		e.printStackTrace();
	            	}
	            }
	        });
		} catch (Exception e){
			JOptionPane.showMessageDialog(null, e.getMessage(), "信息", JOptionPane.ERROR_MESSAGE);
		}
	}
	
	private AboutFrame about;
		// Constructor of the game
	public AppGui() throws Exception {
		super("和平之翼代码生成器SMEU版");
		
		BorderLayout layout = new BorderLayout();
		this.getContentPane().setLayout(layout);

		
		String windows="com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
		UIManager.setLookAndFeel(windows);
		
//		UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
        DefaultSyntaxKit.initKit();	
        initComponents();
        jCmbLangs.setModel(new DefaultComboBoxModel(DefaultSyntaxKit.getContentTypes()));
        jEdtTest.setContentType(jCmbLangs.getItemAt(0).toString());
        jCmbLangs.setSelectedItem("text/sgs");
        Font font = jEdtTest.getFont();
        Font newFont = new Font(font.getName(),font.getStyle(),18);
        jEdtTest.setFont(newFont);
        CaretMonitor cm = new CaretMonitor(jEdtTest, lblCaretPos);
		layout.addLayoutComponent(this.getContentPane(), BorderLayout.CENTER);
		
		this.setTitle("和平之翼代码生成器SMEU版");
		// Begin Menu Set
		mb = new JMenuBar();
		mFile = new JMenu("文件");
		miNew = new JMenuItem("新建");
		miNew.addActionListener(this);
		miOpen = new JMenuItem("打开");
		miOpen.addActionListener(this);
		miSave = new JMenuItem("保存");
		miSave.addActionListener(this);
		miSaveAs= new JMenuItem("另存为...");
		miSaveAs.addActionListener(this);
		miClose = new JMenuItem("关闭");
		miClose.addActionListener(this);
		miExit = new JMenuItem("退出");
		miExit.addActionListener(this);
		mFile.add(miNew);
		mFile.add(miOpen);
		mFile.add(miSave);
		mFile.add(miSaveAs);
		mFile.addSeparator();
		mFile.add(miClose);
		mFile.addSeparator();
		mFile.add(miExit);
		mb.add(mFile);
		
		mSample = new JMenu("示例");
		miGenerateSample = new JMenuItem("GenerateSample示例");
		miGenerateSample.addActionListener(this);
		miMagic = new JMenuItem("魔法语句示例");
		miMagic.addActionListener(this);
		miAdvanced= new JMenuItem("先进特性示例");
		miAdvanced.addActionListener(this);
		miOne = new JMenuItem("One示例");
		miOne.addActionListener(this);
		miEmployeeTest = new JMenuItem("EmployeeTest示例");
		miEmployeeTest.addActionListener(this);
		miUserSystem = new JMenuItem("用户系统示例");
		miUserSystem.addActionListener(this);
		miFields= new JMenuItem("场馆管理系统示例");
		miFields.addActionListener(this);
		miSports= new JMenuItem("运动示例");
		miSports.addActionListener(this);
		miProject = new JMenuItem("项目管理示例");
		miProject.addActionListener(this);
		mSample.add(miGenerateSample);
		mSample.add(miMagic);
		mSample.add(miAdvanced);
		mSample.add(miOne);
		mSample.add(miEmployeeTest);
		mSample.add(miUserSystem);
		mSample.add(miFields);
		mSample.add(miSports);
		mSample.add(miProject);
		mb.add(mSample);

		mCompile = new JMenu("编译");
		miCompile = new JMenuItem("编译");
		miCompile.addActionListener(this);
		mCompile.add(miCompile);
		miIgnore = new JMenuItem("忽略警告并编译");
		miIgnore.addActionListener(this);
		mCompile.add(miIgnore);
		mb.add(mCompile);
		
		mHelp = new JMenu("帮助");
		miReadme = new JMenuItem("阅读说明");
		miReadme.addActionListener(this);
		miInstall = new JMenuItem("下载安装运行文档");
		miInstall.addActionListener(this);
		miUserManual = new JMenuItem("下载用户手册");
		miUserManual.addActionListener(this);
		miTheory1 = new JMenuItem("下载理论文档一");
		miTheory1.addActionListener(this);
		miTheory2 = new JMenuItem("下载理论文档二");
		miTheory2.addActionListener(this);
		miTheory3 = new JMenuItem("下载理论文档三");
		miTheory3.addActionListener(this);
		miTheory4 = new JMenuItem("下载理论文档四");
		miTheory4.addActionListener(this);
		miGift = new JMenuItem("下载神秘礼物");
		miGift.addActionListener(this);
		miAbout = new JMenuItem("关于...");
		miAbout.addActionListener(this);
		mHelp.add(miReadme);
		mHelp.add(miInstall);
		mHelp.add(miUserManual);
		mHelp.add(miTheory1);
		mHelp.add(miTheory2);
		mHelp.add(miTheory3);
		mHelp.add(miTheory4);
		mHelp.add(miGift);
		mHelp.add(miAbout);
		
		mb.add(mHelp);
		this.setJMenuBar(mb);

		// end of Menu Set
		fileActions = new FileActions();
		fileActions.fileName = "";
		fileActions.fileExtension = "";
		readSgs("/sgs/GenerateSample.sgs");
		jEdtTest.setCaretPosition(0);		

		setSize(900, 1200);
		setLocationRelativeTo(null);//窗口在屏幕中间显示
		setVisible(true);
		
		// About Frame
		about = new AboutFrame("关于代码生成器");
	}

	public void actionPerformed(ActionEvent e) {
		try {
			if (e.getSource() == miAbout) {
				about.setVisible(true);
			}
			if (e.getSource() == miGenerateSample){
				readSgs("/sgs/GenerateSample.sgs");  
			}
			if (e.getSource() == miMagic){
				readSgs("/sgs/GenerateCallMagic.sgs");  
			}
			if (e.getSource() == miAdvanced){
				readSgs("/sgs/GenerateAdvanced.sgs");  
			}
			if (e.getSource() == miOne){
				readSgs("/sgs/one.sgs");  
			}
			if (e.getSource() == miEmployeeTest){
				readSgs("/sgs/employeetest.sgs");  
			}
			if (e.getSource() == miUserSystem){
				readSgs("/sgs/usersystems.sgs");  
			}
			if (e.getSource() == miFields){
				readSgs("/sgs/myareas.sgs");  
			}
			if (e.getSource() == miSports){
				readSgs("/sgs/mysports.sgs");  
			}
			if (e.getSource() == miProject){
				readSgs("/sgs/myproject.sgs");  
			}
			if (e.getSource() == miReadme){
				readText("/docs/Readme.txt");  
			}
			if (e.getSource() == miInstall){
				downloadRes("/docs/PeaceWingSMEU_Swing_InstallUsage_1_6.docx","PeaceWingSMEU_Swing_InstallUsage_1_6.docx");  
			}
			if (e.getSource() == miUserManual){
				downloadRes("/docs/PeaceWingSMEU_Swing_UserManual_1_6.docx","PeaceWingSMEU_Swing_UserManual_1_6.docx");  
			}
			if (e.getSource() == miTheory1){
				downloadRes("/docs/超级语言.pptx","超级语言.pptx");  
			}
			if (e.getSource() == miTheory2){
				downloadRes("/docs/代码生成原理浅析.ppt","代码生成原理浅析.ppt");  
			}
			if (e.getSource() == miTheory3){
				downloadRes("/docs/动词算子式通用目的代码生成器基础理论讲纲Update2.pptx","动词算子式通用目的代码生成器基础理论讲纲Update2.pptx");  
			}
			if (e.getSource() == miTheory4){
				downloadRes("/docs/Infinity面向棱柱动词算子式通用目的代码生成器详细设计Update3.ppt","Infinity面向棱柱动词算子式通用目的代码生成器详细设计Update3.ppt");  
			}
			if (e.getSource() == miGift){
				String [] fileNames = {"clocksimplejee4_0_98.zip","TestDemo_allcorrect_20170410.zip"};
				String fileName = fileNames[(int)(Math.random()*2.0)];
				downloadRes("/docs/"+fileName,fileName);  
			}
			if (e.getSource() == miCompile){
				try {
					CompileAction action = new CompileAction();
					action.compilePack(jEdtTest.getText());
					JOptionPane.showMessageDialog(null,  "恭喜，编译已经成功！","编译成功", JOptionPane.INFORMATION_MESSAGE);
				}catch(ValidateException ev){
					ev.printStackTrace();
					List<String> errors = ev.getValidateInfo().getCompileErrors();
					StringBuilder errStr = new StringBuilder();
					for (String s:errors) errStr.append(s).append("\n");
					List<String> warnings = ev.getValidateInfo().getCompileWarnings();
					StringBuilder warnStr = new StringBuilder();
					for (String s:warnings) warnStr.append(s).append("\n");
					if (errors!=null&&errors.size()>0) JOptionPane.showMessageDialog(null, errStr.toString(),"编译失败", JOptionPane.ERROR_MESSAGE);
					if (warnings!=null&&warnings.size()>0) JOptionPane.showMessageDialog(null, warnStr.toString(),"编译失败", JOptionPane.WARNING_MESSAGE);
				}catch(Exception ex){
					ex.printStackTrace();
					JOptionPane.showMessageDialog(null, ex.getMessage(),"编译失败", JOptionPane.ERROR_MESSAGE);
				}
			}
			
			if (e.getSource() == miIgnore){
				try {
					CompileAction action = new CompileAction();
					action.ignoreWarningAndCompilePack(jEdtTest.getText());
					JOptionPane.showMessageDialog(null,  "恭喜，编译已经成功！","编译成功", JOptionPane.INFORMATION_MESSAGE);
				}catch(ValidateException ev){
					ev.printStackTrace();
					List<String> errors = ev.getValidateInfo().getCompileErrors();
					StringBuilder errStr = new StringBuilder();
					for (String s:errors) errStr.append(s).append("\n");
					if (errors!=null && errors.size()>0) JOptionPane.showMessageDialog(null, errStr.toString(),"编译失败", JOptionPane.ERROR_MESSAGE);
				}				
			}
			
			if (e.getSource() == miOpen){
				String contents = fileActions.fileOpen();
				String extension = fileActions.fileExtension;
				if ("sgs".equalsIgnoreCase(extension)){
					jCmbLangs.setSelectedItem("text/sgs");
				}else{
					jCmbLangs.setSelectedItem("text/text");
				}
				jEdtTest.setText(contents);
				jEdtTest.setCaretPosition(0);
				Font font = jEdtTest.getFont();
			    Font newFont = new Font(font.getName(),font.getStyle(),18);
			    jEdtTest.setFont(newFont);
			}
			if (e.getSource() == miSave){
				if (fileActions.fileName.equals("")){
					String newFile = fileActions.fileSaveAs();
					File f = new File(newFile);					
					if (!f.exists()){
						Files.write(f.toPath(), jEdtTest.getText().getBytes(), StandardOpenOption.CREATE_NEW);	
					}else {
						Files.write(f.toPath(), jEdtTest.getText().getBytes(), StandardOpenOption.TRUNCATE_EXISTING);	
					}
					fileActions.fileName = newFile;
				} else { 
					String newFile = fileActions.fileName;
					File f = new File(newFile);
					if (!f.exists()){
						Files.write(f.toPath(), jEdtTest.getText().getBytes(), StandardOpenOption.CREATE_NEW);	
					}else {
						Files.write(f.toPath(), jEdtTest.getText().getBytes(), StandardOpenOption.TRUNCATE_EXISTING);	
					}
				}
			}
			if (e.getSource() == miSaveAs){
				String newFile = fileActions.fileSaveAs();
				File f = new File(newFile);
				if (!f.getName().equals("")&&!f.getName().equals(".sgs")){
					if (!f.exists()){
						Files.write(f.toPath(), jEdtTest.getText().getBytes(), StandardOpenOption.CREATE_NEW);	
					}else {
						Files.write(f.toPath(), jEdtTest.getText().getBytes(), StandardOpenOption.TRUNCATE_EXISTING);	
					}
					fileActions.fileName = newFile;
				}
			}
			if (e.getSource() == miNew){
				fileActions.fileName = "";
				fileActions.fileExtension = "";
				jCmbLangs.setSelectedItem("text/sgs");
				jEdtTest.setText("");
				jEdtTest.setCaretPosition(0);
				Font font = jEdtTest.getFont();
			    Font newFont = new Font(font.getName(),font.getStyle(),18);
			    jEdtTest.setFont(newFont);
			}
		} catch (Exception ie) {
			ie.printStackTrace();;
		}
	}
	
	protected void readSgs(String fileName)throws Exception{
		jCmbLangs.setSelectedItem("text/sgs");
		List<String> contents = new Resource().getResourceStr(fileName);
		jEdtTest.removeAll();
		StringBuilder content = new StringBuilder();
		for (String s:contents) content.append(s).append("\n");
        Font font = jEdtTest.getFont();
        Font newFont = new Font(font.getName(),font.getStyle(),18);
        jEdtTest.setFont(newFont);
		jEdtTest.setText(content.toString());
		jEdtTest.setCaretPosition(0);
		fileActions.fileName = "";
		fileActions.fileExtension = "";
	}
	
	protected void readText(String fileName)throws Exception{
		List<String> contents = new Resource().getResourceStr(fileName);
		jCmbLangs.setSelectedItem("text/text");
		jEdtTest.setText("");
        Font font = jEdtTest.getFont();
        Font newFont = new Font(font.getName(),font.getStyle(),18);
        jEdtTest.setFont(newFont);
		StringBuilder content = new StringBuilder();
		for (String s:contents) content.append(s).append("\n");
		jEdtTest.setText(content.toString());
		jEdtTest.setCaretPosition(0);
		fileActions.fileName = "";
		fileActions.fileExtension = "";
	}
	
	protected void downloadRes(String filePath, String newFileName)throws Exception{
		new Resource().downloadRes(filePath,newFileName);
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        lblCaretPos = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jEdtTest = new javax.swing.JEditorPane();
        lblToken = new javax.swing.JLabel();
        jCmbLangs = new javax.swing.JComboBox();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("JSyntaxPane Tester");

        lblCaretPos.setText("Caret Position");

        jEdtTest.setContentType("");
        jEdtTest.setFont(new java.awt.Font("Monospaced", 0, 13));
        jEdtTest.addCaretListener(new javax.swing.event.CaretListener() {
            public void caretUpdate(javax.swing.event.CaretEvent evt) {
                jEdtTestCaretUpdate(evt);
            }
        });
        jScrollPane1.setViewportView(jEdtTest);

        lblToken.setFont(new java.awt.Font("Courier New", 0, 12));
        lblToken.setText("Token under cursor");

        jCmbLangs.setMaximumRowCount(20);
        jCmbLangs.setFocusable(false);
        jCmbLangs.setVisible(false);
        jCmbLangs.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                jCmbLangsItemStateChanged(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(lblToken, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 612, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jCmbLangs, 0, 231, Short.MAX_VALUE)
                        .addGap(262, 262, 262)
                        .addComponent(lblCaretPos, javax.swing.GroupLayout.PREFERRED_SIZE, 119, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 612, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 395, Short.MAX_VALUE)
                .addGap(2, 2, 2)
                .addComponent(lblToken, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jCmbLangs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lblCaretPos, javax.swing.GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents
   	
	private void jEdtTestCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_jEdtTestCaretUpdate
	    if (jEdtTest.getDocument() instanceof SyntaxDocument) {
	        SyntaxDocument sDoc = (SyntaxDocument) jEdtTest.getDocument();
	        Token t = sDoc.getTokenAt(evt.getDot());
	        if (t != null) {
	            try {
	                String tData = sDoc.getText(t.start, Math.min(t.length, 40));
	                if (t.length > 40) {
	                    tData += "...";
	                }
	                lblToken.setText(t.toString() + ": " + tData);
	            } catch (BadLocationException ex) {
	                // should not happen.. and if it does, just ignore it
	                System.err.println(ex);
	                ex.printStackTrace();
	            }
	        }
	    }

	}
	

private void jCmbLangsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jCmbLangsItemStateChanged
    if (evt.getStateChange() == ItemEvent.SELECTED) {
        String lang = jCmbLangs.getSelectedItem().toString();

        // save the state of the current JEditorPane, as it's Document is about
        // to be replaced.
        String t = jEdtTest.getText();
        int caretPosition = jEdtTest.getCaretPosition();
        Rectangle visibleRectangle = jEdtTest.getVisibleRect();

        // install a new DefaultSyntaxKit on the JEditorPane for the requested language.
        jEdtTest.setContentType(lang);

        // restore the state of the JEditorPane - note that installing a new
        // EditorKit causes the Document to be recreated.
        SyntaxDocument sDoc = (SyntaxDocument) jEdtTest.getDocument();
        jEdtTest.setText(t);
        sDoc.clearUndos();
        jEdtTest.setCaretPosition(caretPosition);
        jEdtTest.scrollRectToVisible(visibleRectangle);
    }
}

//Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JComboBox jCmbLangs;
private javax.swing.JEditorPane jEdtTest;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel lblCaretPos;
private javax.swing.JLabel lblToken;
// End of variables declaration//GEN-END:variables
}



